package com.anjubao.parking.municipal.payment.service;

import com.anjubao.parking.municipal.common.dto.ApiResult;
import com.anjubao.parking.municipal.common.rocketmq.core.RocketMQTemplate;
import com.anjubao.parking.municipal.common.utils.MunicipalParkingUtils;
import com.anjubao.parking.municipal.common.utils.U;
import com.anjubao.parking.municipal.payment.constant.OrderStatusEnum;
import com.anjubao.parking.municipal.payment.constant.PayChannelIdEnum;
import com.anjubao.parking.municipal.payment.constant.PaymentConstant;
import com.anjubao.parking.municipal.payment.dto.PayNotifyDto;
import com.anjubao.parking.municipal.payment.feign.ParkingTradeUserClient;
import com.anjubao.parking.municipal.payment.mapper.ParkingTradeOrderMapper;
import com.anjubao.parking.municipal.payment.mapper.ParkingTradePayHookMapper;
import com.anjubao.parking.municipal.payment.mapper.ParkingTradeRechargeMapper;
import com.anjubao.parking.municipal.payment.model.ParkingTradeOrder;
import com.anjubao.parking.municipal.payment.model.ParkingTradePayHook;
import com.anjubao.parking.municipal.payment.model.ParkingTradeRecharge;
import com.anjubao.parking.municipal.user.constants.BalanceTypeEnum;
import com.anjubao.parking.municipal.user.dto.UserInfoDto;
import com.anjubao.parking.municipal.user.form.UserBalancePayForm;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.client.producer.SendResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @author zhuchunfeng
 * @date 2019/4/26 15:42
 */
@Service
@Slf4j
public class WeiXinNotifyService {

    @Autowired
    private WxPayService wxPayService;
    @Resource
    private ParkingTradeOrderMapper parkingTradeOrderMapper;
    @Resource
    private ParkingTradePayHookMapper parkingTradePayHookMapper;
    @Resource
    private RocketMQTemplate rocketMQTemplate;
    @Resource
    private ParkingTradeRechargeMapper parkingTradeRechargeMapper;
    @Autowired
    private ParkingTradeUserClient parkingTradeUserClient;


    public String parseOrderNotifyResult(@RequestBody String xmlData) {

        /*支付回调验签*/
        final WxPayOrderNotifyResult notifyResult;
        try {
            notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);
        } catch (WxPayException e) {
            log.error("验签失败 msg {}", e.getMessage());
            return WxPayNotifyResponse.fail("失败");
        }

        if (StringUtils.isBlank(notifyResult.getAttach())) {
            handleOrderNofify(notifyResult, xmlData);
        } else {
            log.info("===========收到用户充值回调: {}", notifyResult.getAttach());
            handleRechargeNotify(notifyResult, xmlData);
        }
        return WxPayNotifyResponse.success("成功");
    }

    private void handleRechargeNotify(WxPayOrderNotifyResult notifyResult, String xmlData) {
        /*更新订单状态 未支付->已支付 根据update判断更新结果*/
        String outTradeNo = notifyResult.getOutTradeNo();
        ParkingTradeRecharge parkingTradeRecharge = new ParkingTradeRecharge()
                //支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
                .setFulfillTime(LocalDateTime.parse(notifyResult.getTimeEnd(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))) //支付时间
                .setStatus(OrderStatusEnum.PAID.getCode()) //已支付
                .setStatusDesc(OrderStatusEnum.PAID.getDesc())
                .setPayChannelId(PayChannelIdEnum.WX_PAY.getCode()) //微信支付
                .setTransactionId(notifyResult.getTransactionId()); //微信支付id

        UpdateWrapper<ParkingTradeRecharge> updateWrapper = new UpdateWrapper<>();
        updateWrapper.setEntity(new ParkingTradeRecharge()
                .setStatus(OrderStatusEnum.UN_PAID.getCode()) //未支付
                .setOutTradeId(MunicipalParkingUtils.getIdByCode(outTradeNo)));
        int update = parkingTradeRechargeMapper.update(parkingTradeRecharge, updateWrapper);

        ParkingTradeRecharge order = parkingTradeRechargeMapper.selectById(MunicipalParkingUtils.getIdByCode(outTradeNo));

        /*保存微信支付回调通知到hook*/
        ParkingTradePayHook hook = new ParkingTradePayHook();
        hook.setId(U.id());
        hook.setPayChannel(PayChannelIdEnum.WX_PAY.getDesc());
        hook.setParams(xmlData);
        hook.setOutTradeId(MunicipalParkingUtils.getIdByCode(outTradeNo));
        hook.setChargeHook("处理成功");
        hook.setCreateTime(LocalDateTime.now());
//        if (update != 1) {
//            if (null == order) {
//                hook.setChargeHook("订单不存在???");
//                log.error("订单不存在???");
//            }
//            else if (notifyResult.getTransactionId().equals(order.getTransactionId())
//                    && notifyResult.getOutTradeNo().equals(order.getOutTradeNo()) && order.getStatus() == OrderStatusEnum.PAID.getCode()) {
//                hook.setChargeHook("重复通知");
//                log.info("重复通知");
//            }
//            //重复支付 TODO 通知进行退款处理
//            else if (order.getStatus() == OrderStatusEnum.PAID.getCode()) {
//                hook.setChargeHook("订单重复支付");
//                log.error("订单重复支付");
//            }
//            //掉单 TODO 通知进行补单或退款处理
//            else if (order.getStatus() != OrderStatusEnum.PAID.getCode()) {
//                hook.setChargeHook("掉单");
//                log.error("掉单");
//            } else {
//                hook.setChargeHook("未知错误");
//                log.error("未知错误");
//            }
//        }else {
        UserBalancePayForm userBalancePayForm = new UserBalancePayForm();
        userBalancePayForm.setUserCode(notifyResult.getAttach());
        userBalancePayForm.setAmount(notifyResult.getTotalFee());
        userBalancePayForm.setType(BalanceTypeEnum.RECHARGE.getCode());
        userBalancePayForm.setTradeOrderId(String.valueOf(MunicipalParkingUtils.getIdByCode(outTradeNo)));
        parkingTradeUserClient.balancePay(userBalancePayForm);

        /*发送mq通知子系统支付成功*/
        PayNotifyDto payNotifyDto = new PayNotifyDto();
        payNotifyDto.setBusinessId(order.getBusinessId());
        payNotifyDto.setPayTime(LocalDateTime.parse(notifyResult.getTimeEnd(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        payNotifyDto.setOpenid(order.getPayerOpenid());
        payNotifyDto.setStatus(OrderStatusEnum.PAID.getCode());
        SendResult sendResult = rocketMQTemplate.syncSend(PaymentConstant.payNotifyTopic, payNotifyDto);
        log.info("发送支付回调通知,topic: {} msg: {} sendResult: {}", PaymentConstant.payNotifyTopic, U.json(payNotifyDto), U.json(sendResult));
//        }
        parkingTradePayHookMapper.insert(hook);
    }

    private void handleOrderNofify(WxPayOrderNotifyResult notifyResult, String xmlData) {
        /*更新订单状态 未支付->已支付 根据update判断更新结果*/
        String outTradeNo = notifyResult.getOutTradeNo();
        ParkingTradeOrder parkingTradeOrder = ParkingTradeOrder.builder()
                //支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
                .fulfillTime(LocalDateTime.parse(notifyResult.getTimeEnd(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))) //支付时间
                .status(OrderStatusEnum.PAID.getCode()) //已支付
                .statusDesc(OrderStatusEnum.PAID.getDesc())
                .payChannelId(PayChannelIdEnum.WX_PAY.getCode()) //微信支付
                .transactionId(notifyResult.getTransactionId()) //微信支付id
                .build();
        UpdateWrapper<ParkingTradeOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.setEntity(ParkingTradeOrder.builder()
                .status(OrderStatusEnum.UN_PAID.getCode()) //未支付
                .outTradeId(MunicipalParkingUtils.getIdByCode(outTradeNo)) //id
                .build());
        int update = parkingTradeOrderMapper.update(parkingTradeOrder, updateWrapper);

        ParkingTradeOrder order = parkingTradeOrderMapper.selectById(MunicipalParkingUtils.getIdByCode(outTradeNo));

        /*保存微信支付回调通知到hook*/
        ParkingTradePayHook hook = new ParkingTradePayHook();
        hook.setId(U.id());
        hook.setPayChannel(PayChannelIdEnum.WX_PAY.getDesc());
        hook.setParams(xmlData);
        hook.setOutTradeId(MunicipalParkingUtils.getIdByCode(outTradeNo));
        hook.setChargeHook("处理成功");
        hook.setCreateTime(LocalDateTime.now());
        if (update != 1) {
            if (null == order) {
                hook.setChargeHook("订单不存在???");
                log.error("订单不存在???");
            } else if (notifyResult.getTransactionId().equals(order.getTransactionId())
                    && notifyResult.getOutTradeNo().equals(order.getOutTradeNo()) && order.getStatus() == OrderStatusEnum.PAID.getCode()) {
                hook.setChargeHook("重复通知");
                log.info("重复通知");
            }
            //重复支付 TODO 通知进行退款处理
            else if (order.getStatus() == OrderStatusEnum.PAID.getCode()) {
                hook.setChargeHook("订单重复支付");
                log.error("订单重复支付");
            }
            //掉单 TODO 通知进行补单或退款处理
            else if (order.getStatus() != OrderStatusEnum.PAID.getCode()) {
                hook.setChargeHook("掉单");
                log.error("掉单");
            } else {
                hook.setChargeHook("未知错误");
                log.error("未知错误");
            }
        } else {
            /*发送mq通知子系统支付成功*/
            PayNotifyDto payNotifyDto = new PayNotifyDto();
            payNotifyDto.setBusinessId(order.getBusinessId());
            payNotifyDto.setPayTime(LocalDateTime.parse(notifyResult.getTimeEnd(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
            payNotifyDto.setOrderType(order.getType());
            payNotifyDto.setOpenid(order.getPayerOpenid());
            payNotifyDto.setStatus(OrderStatusEnum.PAID.getCode());
            SendResult sendResult = rocketMQTemplate.syncSend(PaymentConstant.payNotifyTopic, payNotifyDto);
            log.info("发送支付回调通知,topic: {} msg: {} sendResult: {}", PaymentConstant.payNotifyTopic, U.json(payNotifyDto), U.json(sendResult));
        }
        parkingTradePayHookMapper.insert(hook);
    }

}
